/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Lenovo
 * Date: 2025-04-01
 * Time: 8:51
 */
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
// 主程序入口类
public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("========== 1. 多态对象创建 ==========");
        Animal animal1 = new Dog("旺财", 1);   // 多态：编译时类型Animal，运行时类型Dog
        Dog dog = new Dog("小白", 2);         // 具体类型引用
        Animal animal = new Animal(); // 直接父类实例
        System.out.println("\n");

        System.out.println("========== 2. 运行时类型识别 ==========");
        // getClass()始终返回实际类型的Class对象
        Class<?> class1 = animal1.getClass();  // 返回Dog.class
        Class<?> class2 = dog.getClass();      // Dog.class
        Class<?> class3 = animal.getClass();   // Animal.class
        System.out.println("\n");



        System.out.println( "==========  3. 类信息验证 ==========");
        System.out.println("animal1的运行时类名: " + class1.getName());//Dog
        System.out.println("animal1的简单类名: " + class1.getSimpleName());//Dog
        System.out.println("dog的运行时类名: " +class2.getName());//Dog
        System.out.println("animal的运行时类名: " +class3.getName());//Animal
        System.out.println("animal1是否为接口：" + class1.isInterface());    // false
        System.out.println("dog父类：" + class2.getSuperclass().getName()); // Animal
        System.out.println("\n");

        System.out.println(" ========== 4. Class对象特性验证 ==========");
        System.out.println("Dog类Class对象是否唯一: " + (class1 == class2)); // true
        System.out.println("Animal与Dog的Class对象: " + (animal.getClass() == dog.getClass())); // false
        System.out.println(class1 == Animal.class); //false
        System.out.println(class2 == Animal.class);//false
        System.out.println(class3 == Animal.class);//true
        System.out.println(class1 == Dog.class);//true
        System.out.println(class2 == Dog.class);//true
        System.out.println(class3 == Dog.class);//false
        System.out.println("\n");

        Class<?> dogClass = Dog.class;//获取Class对象另一种方式
        System.out.println(" ========== 字段反射操作 ==========");
        System.out.println("==== 公有字段操作 ====");
        Field dogageField = dogClass.getField("age");
        System.out.println("dog对象原始年龄：" + dogageField.get(dog));//读取字段值,输出：dog对象原始年龄：2
        dogageField.set(dog, 5);  // 修改字段值
        System.out.println("dog对象修改后年龄：" + dogageField.get(dog));//读取字段值，输出：dog对象修改后年龄：5
        //
        Field animal1agefield = class1.getField("age");  // 获取公共字段
        System.out.println("animal1对象原始年龄：" + animal1agefield.get(animal1));//读取字段值，输出：animal1对象原始年龄：1
        animal1agefield.set(animal1, 8);  // 修改字段值
        System.out.println("animal1对象修改后年龄：" + animal1agefield.get(animal1));//animal1对象修改后年龄：8

        System.out.println("==== 私有字段操作 ====");
        Field dognameField = dogClass.getDeclaredField("name");//获取Dog类私有字段name
        dognameField.setAccessible(true);  // 突破访问限制
        System.out.println("dog对象原始姓名：" + dognameField.get(dog));//输出：dog对象原始姓名：小白
        dognameField.set(dog, "小黑");// 修改私有字段
        System.out.println("dog对象修改后姓名：" + dognameField.get(dog));//输出：dog对象修改后姓名：小黑
        //
        Field animal1nameField = class1.getDeclaredField("name");//获取私有字段
        animal1nameField.setAccessible(true);  // 突破访问限制
        System.out.println("原始姓名：" + animal1nameField.get(animal1));//输出：原始姓名：旺财
        animal1nameField.set(animal1, "大黄");// 修改私有字段
        System.out.println("修改后姓名：" + animal1nameField.get(animal1));//输出：修改后姓名：大黄
        //
        System.out.println("========== 反射方法操作 ==========");
        System.out.println("==== 公共方法调用 ====");
        Method print = dogClass.getMethod("print"); //获取公共方法
        print.invoke(dog);//调用方法。输出：姓名：小黑 年龄：5
        //
        System.out.println("==== 私有方法调用 ====");
        Method setName = dogClass.getDeclaredMethod("setName", String.class);  // 获取私有方法
        setName.setAccessible(true);  // 突破访问限制
        setName.invoke(dog, "小粉");  // 调用私有方法，输出：子类Dog私有方法被调用，新名字：小粉
        print.invoke(dog);//输出：姓名：小粉 年龄：5

        //
        System.out.println(" ========== 反射构造器操作 ==========");
        System.out.println("==== 创建实例 ====");
        // 正常公有构造器
        Constructor<?> dogConstructor = dogClass.getDeclaredConstructor(String.class, int.class);
        Dog  reflectDog = (Dog) dogConstructor.newInstance("小黄", 3);  // 反射创建对象
        //上面代码要注意无论通过反射还是直接 new 创建对象，Java强制要求父类构造方法在子类构造方法之前执行。所以会先跳到基类构造器执行
        reflectDog.print();
        System.out.println("\n");
        /*输出：
        基类Animal的默认构造器（包级访问）
        子类Dog公有构造器
        姓名：小黄 年龄：3*/


        // 包级访问构造器（同包内可直接访问）
        Constructor<?> animalConstructor = class3.getDeclaredConstructor();
        Animal reflectAnimal = (Animal) animalConstructor.newInstance();
        reflectAnimal.eat();
        System.out.println("\n");
        /*输出：
         基类Animal的默认构造器（包级访问）
         动物吃饭！！！*/

        // 私有构造器（需要突破访问限制）
        Class<?> catClass = Cat.class;
        Constructor<?> catConstructor = catClass.getDeclaredConstructor(String.class);
        catConstructor.setAccessible(true); // 允许访问私有构造器
        Cat reflectCat = (Cat) catConstructor.newInstance("咪咪");
        reflectCat.eat();
        /*输出：
        基类Animal的默认构造器（包级访问）
        子类Cat私有构造器调用
        咪咪吃猫粮
        */
    }
}